#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "job.h"

job_info *jobs;          /* job link for all jobs, jobs[0] is front process */

void init_jobs()
{
    jobs = malloc(sizeof(job_info));
    jobs->jid = 0;
    jobs->pgid = 0;
    jobs->alive = 0;
    jobs->run = 0;
    jobs->status = NULL;
    jobs->cmdline = NULL;
    jobs->next = NULL;
}

void free_jobs()
{
    job_info *job = jobs, *next;
    
    while (job != NULL) {
        next = job->next;
        free(job->cmdline);
        free(job);
        job = next;
    }
}

void print_jobs()
{
    job_info *job = jobs->next;

    while (job != NULL) {
        printf("Job [%d] %s %s\n", job->jid, job->cmdline, job->status);
        job = job->next;
    }
}

/* add a new job*/
void add_job(pid_t pgid, int alive_count, int run_count, char *status, char *cmdline)
{
    job_info *job = jobs, *new_job;

    new_job = malloc(sizeof(job_info));
    new_job->pgid = pgid;
    new_job->alive = alive_count;
    new_job->run = run_count;
    new_job->status = status;
    new_job->cmdline = cmdline;
    new_job->next = NULL;

    while (job->next != NULL)
        job = job->next;

    job->next = new_job;
    new_job->jid = job->jid+1;
}

/* delete the job with gid */
void del_job(pid_t pgid)
{
    int find = 0;
    job_info *deljob, *job = jobs;

    while (job->next != NULL) {
        if (job->next->pgid == pgid) {
            find = 1;
            deljob = job->next;
            job->next = deljob->next;
            free(deljob->cmdline);
            free(deljob);
            continue;
        }
        if (find)
            job->next->jid --;

        job = job->next;
    }
}

/* set the job's status and cmdline with pid and retrun the new job_info */
job_info *set_job(pid_t pgid, char *status, int cmd_set) 
{
    job_info *job = jobs->next;
    char *newcmdline;
    int cmdlen;

    while (job != NULL) {
        if (job->pgid == pgid) {
            if (status != NULL && status != job->status)
                job->status = status;
            switch (cmd_set)
            {
                case SET_BG:
                    if (strrchr(job->cmdline, '&') == NULL) {
                        cmdlen = strlen(job->cmdline);
                        newcmdline = malloc(cmdlen+3);
                        strncpy(newcmdline, job->cmdline, cmdlen);
                        newcmdline[cmdlen] = ' ';
                        newcmdline[cmdlen+1] = '&';
                        newcmdline[cmdlen+2] = '\0';
                        free(job->cmdline);
                        job->cmdline = newcmdline;
                    }
                    break;
                case SET_FG:
                    if ((newcmdline = strrchr(job->cmdline, '&')) != NULL) {
                        newcmdline[-1] = '\0';
                    }
                    break;
                default:
                    break;
            }
            return job;
        }
        job = job->next;
    }

    return NULL;
}

/* find the job by jid or pid */
job_info *find_job(int jid, pid_t pgid)
{
    job_info *job = jobs->next;

    if (jid == 0 && pgid == 0)
        return NULL;

    while (job != NULL) {
        if (job->jid == jid)
            return job;
        else if (job->pgid == pgid)
            return job;
        job = job->next;
    }

    return NULL;
}
